from django_redis import get_redis_connection
from rest_framework import serializers
import re

from users.models import User


class CreateUserSerializer(serializers.ModelSerializer):
    """用户注册序列化器"""

    # 提供用户模型类没有的字段, 这些字段都只在序列化时时候有效
    sms_code = serializers.CharField(label="短信验证码", write_only=True)
    password2 = serializers.CharField(label="确认密码", write_only=True)
    allow = serializers.CharField(label="同意协议", write_only=True)

    class Meta:
        model = User
        # 需要进行反序列化的字段
        fields = ('id', 'username', 'password', 'password2', 'sms_code', 'mobile', 'allow')
        # 反序列化的时候需要对字段进行校验

        # 1.用户名,密码---长度为6-20
        extra_kwargs = {
            'username': {
                'min_length': 6,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许6-20个字符的用户名',
                    'max_length': '仅允许6-20个字符的用户名'
                }
            },
            'password': {
                'write_only': True,
                'min_length': 6,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许6-20个字符的密码',
                    'max_length': '仅允许6-20个字符的用密码'
            }
        }
        }

    # 2.手机号---通过正则匹配
    def validate_mobile(self, value):
        if not re.match(r"^1[3-8]\d{9}$", value):
            raise serializers.ValidationError("手机号输入错误")
        return value

    # 3.同意协议--为True
    def validate_allow(self, value):
        if value != 'true':
            raise serializers.ValidationError("请勾选同意协议")
        return value

    # 4.密码和确认密码是否相等, 短信验证码是否和redis中相同
    def validate(self, attrs):
        password = attrs["password"]
        password2 = attrs["password2"]
        sms_code = attrs["sms_code"]
        mobile = attrs["mobile"]

        # 判断两次密码是否一致
        if password != password2:
            raise serializers.ValidationError("两次输入密码不一致")

        redis_conn = get_redis_connection("verify_codes")
        real_sms_code = redis_conn.get("sms_%s" % mobile)
        if not real_sms_code:
            raise serializers.ValidationError("短信验证码已失效")

        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError("短信验证码输入错误")

        return attrs

    # 反序列化,通过校验之后,将用户保存保存到服务器,需要将某些字段进行删除
    # 对密码进行加密

    def create(self, validated_data):
        # 删除不需要保存到数据库中的字段信息
        del validated_data['sms_code']
        del validated_data['password2']
        del validated_data['allow']
        # 创建模型化用户对象
        user = super().create(validated_data)
        # 对密码进行加密
        user.set_password(validated_data['password'])

        user.save()
        return user


